static gboolean
import_directory_meta (OstreeRepo *self,
- const char *path,
+ GFile *f,
GVariant **out_variant,
GChecksum **out_checksum,
GError **error)
gboolean ret = FALSE;
GChecksum *ret_checksum = NULL;
GVariant *dirmeta = NULL;
- GFile *f = NULL;
GFileInfo *f_info = NULL;
- f = ot_gfile_new_for_path (path);
-
f_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, error);
goto out;
ret = TRUE;
- *out_variant = dirmeta;
- dirmeta = NULL;
- *out_checksum = ret_checksum;
- ret_checksum = NULL;
+ if (out_variant)
+ {
+ *out_variant = dirmeta;
+ dirmeta = NULL;
+ }
+ if (out_checksum)
+ {
+ *out_checksum = ret_checksum;
+ ret_checksum = NULL;
+ }
out:
- g_clear_object (&f);
g_clear_object (&f_info);
if (ret_checksum)
g_checksum_free (ret_checksum);
return ret;
}
-typedef struct _ParsedTreeData ParsedTreeData;
-typedef struct _ParsedDirectoryData ParsedDirectoryData;
+static GVariant *
+create_empty_gvariant_dict (void)
+{
+ GVariantBuilder builder;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
+ return g_variant_builder_end (&builder);
+}
-static void parsed_tree_data_free (ParsedTreeData *pdata);
+gboolean
+ostree_repo_write_ref (OstreeRepo *self,
+ const char *remote,
+ const char *name,
+ const char *rev,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ OstreeRepoPrivate *priv = GET_PRIVATE (self);
+ GFile *dir = NULL;
-struct _ParsedDirectoryData {
- ParsedTreeData *tree_data;
- char *metadata_sha256;
- GVariant *meta_data;
-};
+ if (remote == NULL)
+ dir = g_object_ref (priv->local_heads_dir);
+ else
+ {
+ dir = g_file_get_child (priv->remote_heads_dir, remote);
-static void
-parsed_directory_data_free (ParsedDirectoryData *pdata)
-{
- if (pdata == NULL)
- return;
- parsed_tree_data_free (pdata->tree_data);
- g_free (pdata->metadata_sha256);
- ot_clear_gvariant (&pdata->meta_data);
- g_free (pdata);
-}
+ if (!ot_gfile_ensure_directory (dir, FALSE, error))
+ goto out;
+ }
-struct _ParsedTreeData {
- GHashTable *files; /* char* filename -> char* checksum */
- GHashTable *directories; /* char* dirname -> ParsedDirectoryData* */
-};
+ if (!write_checksum_file (dir, name, rev, error))
+ goto out;
-static ParsedTreeData *
-parsed_tree_data_new (void)
-{
- ParsedTreeData *ret = g_new0 (ParsedTreeData, 1);
- ret->files = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free,
- (GDestroyNotify)g_free);
- ret->directories = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free,
- (GDestroyNotify)parsed_directory_data_free);
+ ret = TRUE;
+ out:
+ g_clear_object (&dir);
return ret;
}
-static void
-parsed_tree_data_free (ParsedTreeData *pdata)
+static gboolean
+import_commit (OstreeRepo *self,
+ const char *branch,
+ const char *parent,
+ const char *subject,
+ const char *body,
+ GVariant *metadata,
+ GChecksum *root_contents_checksum,
+ GChecksum *root_metadata_checksum,
+ GChecksum **out_commit,
+ GError **error)
{
- if (pdata == NULL)
- return;
- g_hash_table_destroy (pdata->files);
- g_hash_table_destroy (pdata->directories);
- g_free (pdata);
-}
+ gboolean ret = FALSE;
+ GChecksum *ret_commit = NULL;
+ GVariant *commit = NULL;
+ GDateTime *now = NULL;
-static GVariant *
-create_empty_gvariant_dict (void)
-{
- GVariantBuilder builder;
- g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
- return g_variant_builder_end (&builder);
+ g_assert (branch != NULL);
+ g_assert (subject != NULL);
+
+ now = g_date_time_new_now_utc ();
+ commit = g_variant_new ("(u@a{sv}ssstss)",
+ GUINT32_TO_BE (OSTREE_COMMIT_VERSION),
+ metadata ? metadata : create_empty_gvariant_dict (),
+ parent ? parent : "",
+ subject, body ? body : "",
+ GUINT64_TO_BE (g_date_time_to_unix (now)),
+ g_checksum_get_string (root_contents_checksum),
+ g_checksum_get_string (root_metadata_checksum));
+ g_variant_ref_sink (commit);
+ if (!import_gvariant_object (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
+ commit, &ret_commit, error))
+ goto out;
+
+ if (!ostree_repo_write_ref (self, NULL, branch, g_checksum_get_string (ret_commit), error))
+ goto out;
+
+ ret = TRUE;
+ if (out_commit)
+ {
+ *out_commit = ret_commit;
+ ret_commit = NULL;
+ }
+ out:
+ if (ret_commit)
+ g_checksum_free (ret_commit);
+ ot_clear_gvariant (&commit);
+ if (now)
+ g_date_time_unref (now);
+ return ret;
}
static gboolean
-import_parsed_tree (OstreeRepo *self,
- ParsedTreeData *tree,
- GChecksum **out_checksum,
- GError **error)
+import_directory_recurse (OstreeRepo *self,
+ GFile *base,
+ GFile *dir,
+ GChecksum **out_contents_checksum,
+ GChecksum **out_metadata_checksum,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
- GVariant *serialized_tree = NULL;
+ GError *temp_error = NULL;
+ GChecksum *ret_metadata_checksum = NULL;
+ GChecksum *ret_contents_checksum = NULL;
+ GFileEnumerator *dir_enum = NULL;
+ GFileInfo *child_info = NULL;
+ GFile *child = NULL;
+ GHashTable *file_checksums = NULL;
+ GHashTable *dir_metadata_checksums = NULL;
+ GHashTable *dir_contents_checksums = NULL;
+ GChecksum *child_file_checksum = NULL;
+ gboolean did_exist;
gboolean builders_initialized = FALSE;
GVariantBuilder files_builder;
GVariantBuilder dirs_builder;
GHashTableIter hash_iter;
GSList *sorted_filenames = NULL;
GSList *iter;
+ GVariant *serialized_tree = NULL;
gpointer key, value;
+ if (!import_directory_meta (self, dir, NULL, &ret_metadata_checksum, error))
+ goto out;
+
+ dir_enum = g_file_enumerate_children ((GFile*)dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable,
+ error);
+ if (!dir_enum)
+ goto out;
+
+ file_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+ dir_metadata_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+ dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+
+ while ((child_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL)
+ {
+ const char *name = g_file_info_get_name (child_info);
+
+ g_clear_object (&child);
+ child = g_file_get_child (dir, name);
+
+ if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY)
+ {
+ GChecksum *child_dir_metadata_checksum;
+ GChecksum *child_dir_contents_checksum;
+
+ if (!import_directory_recurse (self, base, child, &child_dir_contents_checksum,
+ &child_dir_metadata_checksum, cancellable, error))
+ goto out;
+
+ g_hash_table_replace (dir_contents_checksums, g_strdup (name),
+ g_strdup (g_checksum_get_string (child_dir_contents_checksum)));
+ g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
+ g_strdup (g_checksum_get_string (child_dir_metadata_checksum)));
+ g_checksum_free (child_dir_contents_checksum);
+ g_checksum_free (child_dir_metadata_checksum);
+ }
+ else
+ {
+ if (child_file_checksum)
+ g_checksum_free (child_file_checksum);
+ if (!ostree_checksum_file (child, OSTREE_OBJECT_TYPE_FILE, &child_file_checksum, cancellable, error))
+ goto out;
+
+ if (!ostree_repo_store_object_trusted (self, child, g_checksum_get_string (child_file_checksum),
+ OSTREE_OBJECT_TYPE_FILE, FALSE, &did_exist, error))
+ goto out;
+
+ g_hash_table_replace (file_checksums, g_strdup (name),
+ g_strdup (g_checksum_get_string (child_file_checksum)));
+ }
+
+ g_clear_object (&child_info);
+ }
+ if (temp_error != NULL)
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+
g_variant_builder_init (&files_builder, G_VARIANT_TYPE ("a(ss)"));
g_variant_builder_init (&dirs_builder, G_VARIANT_TYPE ("a(sss)"));
builders_initialized = TRUE;
- g_hash_table_iter_init (&hash_iter, tree->files);
+ g_hash_table_iter_init (&hash_iter, file_checksums);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *name = key;
const char *name = iter->data;
const char *value;
- value = g_hash_table_lookup (tree->files, name);
+ value = g_hash_table_lookup (file_checksums, name);
g_variant_builder_add (&files_builder, "(ss)", name, value);
}
-
+
g_slist_free (sorted_filenames);
sorted_filenames = NULL;
- g_hash_table_iter_init (&hash_iter, tree->directories);
+ g_hash_table_iter_init (&hash_iter, dir_metadata_checksums);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *name = key;
for (iter = sorted_filenames; iter; iter = iter->next)
{
const char *name = iter->data;
- GChecksum *dir_checksum = NULL;
- ParsedDirectoryData *dir;
-
- dir = g_hash_table_lookup (tree->directories, name);
-
- if (!import_parsed_tree (self, dir->tree_data, &dir_checksum, error))
- goto out;
g_variant_builder_add (&dirs_builder, "(sss)",
- name, g_checksum_get_string (dir_checksum), dir->metadata_sha256);
- g_checksum_free (dir_checksum);
+ name,
+ g_hash_table_lookup (dir_contents_checksums, name),
+ g_hash_table_lookup (dir_metadata_checksums, name));
}
g_slist_free (sorted_filenames);
g_variant_builder_end (&dirs_builder));
builders_initialized = FALSE;
g_variant_ref_sink (serialized_tree);
- if (!import_gvariant_object (self, OSTREE_SERIALIZED_TREE_VARIANT, serialized_tree, out_checksum, error))
+
+ if (!import_gvariant_object (self, OSTREE_SERIALIZED_TREE_VARIANT, serialized_tree, &ret_contents_checksum, error))
goto out;
-
+
+ *out_metadata_checksum = ret_metadata_checksum;
+ ret_metadata_checksum = NULL;
+ *out_contents_checksum = ret_contents_checksum;
+ ret_contents_checksum = NULL;
ret = TRUE;
out:
+ g_clear_object (&dir_enum);
+ g_clear_object (&child);
+ g_clear_object (&child_info);
+ g_hash_table_destroy (file_checksums);
+ g_hash_table_destroy (dir_metadata_checksums);
+ g_hash_table_destroy (dir_contents_checksums);
+ if (ret_metadata_checksum)
+ g_checksum_free (ret_metadata_checksum);
+ if (ret_contents_checksum)
+ g_checksum_free (ret_contents_checksum);
+ if (child_file_checksum)
+ g_checksum_free (child_file_checksum);
g_slist_free (sorted_filenames);
if (builders_initialized)
{
return ret;
}
-static gboolean
-check_path (const char *filename,
- GError **error)
-{
- gboolean ret = FALSE;
-
- if (!*filename)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid empty filename");
- goto out;
- }
-
- if (strcmp (filename, ".") == 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Self-reference '.' in filename '%s' not allowed (yet)", filename);
- goto out;
- }
-
- if (ot_util_filename_has_dotdot (filename))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Path uplink '..' in filename '%s' not allowed (yet)", filename);
- goto out;
- }
-
- if (g_path_is_absolute (filename))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Absolute filename '%s' not allowed (yet)", filename);
- goto out;
- }
-
- ret = TRUE;
- out:
- return ret;
-}
-
-static gboolean
-add_one_directory_to_tree_and_import (OstreeRepo *self,
- const char *basename,
- const char *abspath,
- ParsedTreeData *tree,
- ParsedDirectoryData **dir, /*inout*/
- GError **error)
-{
- gboolean ret = FALSE;
- GVariant *dirmeta = NULL;
- GChecksum *dir_meta_checksum = NULL;
- ParsedDirectoryData *dir_value = *dir;
-
- g_assert (tree != NULL);
-
- if (!import_directory_meta (self, abspath, &dirmeta, &dir_meta_checksum, error))
- goto out;
-
- if (dir_value)
- {
- ot_clear_gvariant (&dir_value->meta_data);
- dir_value->meta_data = dirmeta;
- }
- else
- {
- dir_value = g_new0 (ParsedDirectoryData, 1);
- dir_value->tree_data = parsed_tree_data_new ();
- dir_value->metadata_sha256 = g_strdup (g_checksum_get_string (dir_meta_checksum));
- dir_value->meta_data = dirmeta;
- g_hash_table_insert (tree->directories, g_strdup (basename), dir_value);
- }
-
- ret = TRUE;
- *dir = dir_value;
- out:
- if (dir_meta_checksum)
- g_checksum_free (dir_meta_checksum);
- return ret;
-}
-
-static gboolean
-add_one_file_to_tree_and_import (OstreeRepo *self,
- const char *basename,
- const char *abspath,
- ParsedTreeData *tree,
- GError **error)
-{
- gboolean ret = FALSE;
- GChecksum *checksum = NULL;
- gboolean did_exist;
- GFile *f = NULL;
-
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- g_assert (tree != NULL);
-
- f = ot_gfile_new_for_path (abspath);
-
- if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE, &checksum, NULL, error))
- goto out;
-
- if (!ostree_repo_store_object_trusted (self, f, g_checksum_get_string (checksum),
- OSTREE_OBJECT_TYPE_FILE, FALSE, &did_exist, error))
- goto out;
-
- g_hash_table_replace (tree->files, g_strdup (basename),
- g_strdup (g_checksum_get_string (checksum)));
-
- ret = TRUE;
- out:
- g_clear_object (&f);
- if (checksum)
- g_checksum_free (checksum);
- return ret;
-}
-
-static gboolean
-add_one_path_to_tree_and_import (OstreeRepo *self,
- const char *base,
- const char *filename,
- ParsedTreeData *tree,
- GError **error)
-{
- gboolean ret = FALSE;
- GPtrArray *components = NULL;
- struct stat stbuf;
- char *component_abspath = NULL;
- ParsedTreeData *current_tree = tree;
- const char *component = NULL;
- const char *file_sha1;
- char *abspath = NULL;
- ParsedDirectoryData *dir;
- int i;
- gboolean is_directory;
-
- if (!check_path (filename, error))
- goto out;
-
- abspath = g_build_filename (base, filename, NULL);
-
- if (lstat (abspath, &stbuf) < 0)
- {
- ot_util_set_error_from_errno (error, errno);
- goto out;
- }
- is_directory = S_ISDIR(stbuf.st_mode);
-
- if (components)
- g_ptr_array_free (components, TRUE);
- components = ot_util_path_split (filename);
- g_assert (components->len > 0);
-
- current_tree = tree;
- for (i = 0; i < components->len; i++)
- {
- component = components->pdata[i];
- g_free (component_abspath);
- component_abspath = ot_util_path_join_n (base, components, i);
- file_sha1 = g_hash_table_lookup (current_tree->files, component);
- dir = g_hash_table_lookup (current_tree->directories, component);
-
- g_assert_cmpstr (component, !=, ".");
-
- if (i < components->len - 1)
- {
- if (file_sha1 != NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Encountered non-directory '%s' in '%s'",
- component,
- filename);
- goto out;
- }
- /* Implicitly add intermediate directories */
- if (!add_one_directory_to_tree_and_import (self, component,
- component_abspath, current_tree, &dir,
- error))
- goto out;
- g_assert (dir != NULL);
- current_tree = dir->tree_data;
- }
- else if (is_directory)
- {
- if (file_sha1 != NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "File '%s' can't be overwritten by directory",
- filename);
- goto out;
- }
- if (!add_one_directory_to_tree_and_import (self, component,
- abspath, current_tree, &dir,
- error))
- goto out;
- }
- else
- {
- g_assert (!is_directory);
- if (dir != NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "File '%s' can't be overwritten by directory",
- filename);
- goto out;
- }
- if (!add_one_file_to_tree_and_import (self, component, abspath,
- current_tree, error))
- goto out;
- }
- }
-
- ret = TRUE;
- out:
- if (components)
- g_ptr_array_unref (components);
- g_free (component_abspath);
- g_free (abspath);
- return ret;
-}
-
gboolean
-ostree_repo_write_ref (OstreeRepo *self,
- const char *remote,
- const char *name,
- const char *rev,
- GError **error)
-{
- gboolean ret = FALSE;
- OstreeRepoPrivate *priv = GET_PRIVATE (self);
- GFile *dir = NULL;
-
- if (remote == NULL)
- dir = g_object_ref (priv->local_heads_dir);
- else
- {
- dir = g_file_get_child (priv->remote_heads_dir, remote);
-
- if (!ot_gfile_ensure_directory (dir, FALSE, error))
- goto out;
- }
-
- if (!write_checksum_file (dir, name, rev, error))
- goto out;
-
- ret = TRUE;
- out:
- g_clear_object (&dir);
- return ret;
-}
-
-static gboolean
-commit_parsed_tree (OstreeRepo *self,
+ostree_repo_commit (OstreeRepo *self,
const char *branch,
const char *parent,
const char *subject,
const char *body,
GVariant *metadata,
- ParsedDirectoryData *root,
+ GFile *dir,
GChecksum **out_commit,
+ GCancellable *cancellable,
GError **error)
-{
- gboolean ret = FALSE;
- GChecksum *root_checksum = NULL;
- GChecksum *ret_commit = NULL;
- GVariant *commit = NULL;
- GDateTime *now = NULL;
-
- g_assert (branch != NULL);
- g_assert (subject != NULL);
-
- if (!import_parsed_tree (self, root->tree_data, &root_checksum, error))
- goto out;
-
- now = g_date_time_new_now_utc ();
- commit = g_variant_new ("(u@a{sv}ssstss)",
- GUINT32_TO_BE (OSTREE_COMMIT_VERSION),
- metadata ? metadata : create_empty_gvariant_dict (),
- parent ? parent : "",
- subject, body ? body : "",
- GUINT64_TO_BE (g_date_time_to_unix (now)),
- g_checksum_get_string (root_checksum),
- root->metadata_sha256);
- g_variant_ref_sink (commit);
- if (!import_gvariant_object (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
- commit, &ret_commit, error))
- goto out;
-
- if (!ostree_repo_write_ref (self, NULL, branch, g_checksum_get_string (ret_commit), error))
- goto out;
-
- ret = TRUE;
- *out_commit = ret_commit;
- out:
- if (root_checksum)
- g_checksum_free (root_checksum);
- ot_clear_gvariant (&commit);
- if (now)
- g_date_time_unref (now);
- return ret;
-}
-
-static gboolean
-import_root (OstreeRepo *self,
- const char *base,
- ParsedDirectoryData **out_root,
- GError **error)
-{
- gboolean ret = FALSE;
- ParsedDirectoryData *ret_root = NULL;
- GVariant *root_metadata = NULL;
- GChecksum *root_meta_checksum = NULL;
-
- if (!import_directory_meta (self, base, &root_metadata, &root_meta_checksum, error))
- goto out;
-
- ret_root = g_new0 (ParsedDirectoryData, 1);
- ret_root->tree_data = parsed_tree_data_new ();
- ret_root->meta_data = root_metadata;
- root_metadata = NULL;
- ret_root->metadata_sha256 = g_strdup (g_checksum_get_string (root_meta_checksum));
-
- ret = TRUE;
- *out_root = ret_root;
- ret_root = NULL;
- out:
- ot_clear_gvariant (&root_metadata);
- if (root_meta_checksum)
- g_checksum_free (root_meta_checksum);
- parsed_directory_data_free (ret_root);
- return ret;
-}
-
-gboolean
-ostree_repo_commit_from_filelist_fd (OstreeRepo *self,
- const char *branch,
- const char *parent,
- const char *subject,
- const char *body,
- GVariant *metadata,
- const char *base,
- int fd,
- char separator,
- GChecksum **out_commit,
- GError **error)
{
OstreeRepoPrivate *priv = GET_PRIVATE (self);
gboolean ret = FALSE;
- ParsedDirectoryData *root = NULL;
GChecksum *ret_commit_checksum = NULL;
- GUnixInputStream *in = NULL;
- GDataInputStream *datain = NULL;
- char *filename = NULL;
- gsize filename_len;
- GError *temp_error = NULL;
- GVariant *root_metadata = NULL;
- GChecksum *root_meta_checksum = NULL;
+ GChecksum *root_metadata_checksum = NULL;
+ GChecksum *root_contents_checksum = NULL;
char *current_head = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (parent == NULL)
parent = branch;
- /* We're overwriting the tree */
- if (!import_root (self, base, &root, error))
- goto out;
-
if (!ostree_repo_resolve_rev (self, parent, TRUE, ¤t_head, error))
goto out;
- in = (GUnixInputStream*)g_unix_input_stream_new (fd, FALSE);
- datain = g_data_input_stream_new ((GInputStream*)in);
+ if (!import_directory_recurse (self, dir, dir, &root_contents_checksum, &root_metadata_checksum, cancellable, error))
+ goto out;
- while ((filename = g_data_input_stream_read_upto (datain, &separator, 1,
- &filename_len, NULL, &temp_error)) != NULL)
- {
- if (!g_data_input_stream_read_byte (datain, NULL, &temp_error))
- {
- if (temp_error != NULL)
- {
- g_propagate_prefixed_error (error, temp_error, "%s", "While reading filelist: ");
- goto out;
- }
- }
- if (!add_one_path_to_tree_and_import (self, base, filename, root->tree_data, error))
- goto out;
- g_free (filename);
- filename = NULL;
- }
- if (filename == NULL && temp_error != NULL)
- {
- g_propagate_prefixed_error (error, temp_error, "%s", "While reading filelist: ");
- goto out;
- }
- if (!commit_parsed_tree (self, branch, current_head, subject, body, metadata,
- root, &ret_commit_checksum, error))
+ if (!import_commit (self, branch, current_head, subject, body, metadata,
+ root_contents_checksum, root_metadata_checksum, &ret_commit_checksum, error))
goto out;
ret = TRUE;
if (ret_commit_checksum)
g_checksum_free (ret_commit_checksum);
g_free (current_head);
- ot_clear_gvariant (&root_metadata);
- if (root_meta_checksum)
- g_checksum_free (root_meta_checksum);
- g_clear_object (&datain);
- g_clear_object (&in);
- g_free (filename);
- parsed_directory_data_free (root);
+ if (root_metadata_checksum)
+ g_checksum_free (root_metadata_checksum);
+ if (root_contents_checksum)
+ g_checksum_free (root_contents_checksum);
return ret;
}
#include <glib/gi18n.h>
-static gboolean separator_null;
-static int from_fd = -1;
-static gboolean from_stdin;
-static char *from_file;
static char *metadata_text_path;
static char *metadata_bin_path;
static char *subject;
{ "metadata-variant", 0, 0, G_OPTION_ARG_FILENAME, &metadata_bin_path, "File containing serialized variant, in host endianness", "path" },
{ "branch", 'b', 0, G_OPTION_ARG_STRING, &branch, "Branch", "branch" },
{ "parent", 'p', 0, G_OPTION_ARG_STRING, &parent, "Parent commit", "commit" },
- { "from-fd", 0, 0, G_OPTION_ARG_INT, &from_fd, "Read new tree files from fd", "file descriptor" },
- { "from-stdin", 0, 0, G_OPTION_ARG_NONE, &from_stdin, "Read new tree files from stdin", "file descriptor" },
- { "from-file", 0, 0, G_OPTION_ARG_FILENAME, &from_file, "Read new tree files from another file", "path" },
- { "separator-null", 0, 0, G_OPTION_ARG_NONE, &separator_null, "", "Use '\\0' as filename separator, as with find -print0" },
{ NULL }
};
-typedef struct {
- GFile *dir;
- char separator;
- GOutputStream *out;
- GCancellable *cancellable;
-} FindThreadData;
-
-static gboolean
-find (const char *basepath,
- GFile *dir,
- char separator,
- GOutputStream *out,
- GCancellable *cancellable,
- GError **error);
-
-static gboolean
-find_write_child (const char *basepath,
- GFile *dir,
- char separator,
- GOutputStream *out,
- GFileInfo *finfo,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- guint32 type;
- const char *name;
- char buf[1];
- const char *child_path = NULL;
- GString *child_trimmed_path = NULL;
- GFile *child = NULL;
- gsize bytes_written;
-
- type = g_file_info_get_attribute_uint32 (finfo, "standard::type");
- name = g_file_info_get_attribute_byte_string (finfo, "standard::name");
-
- child = g_file_get_child (dir, name);
-
- if (type == G_FILE_TYPE_DIRECTORY)
- {
- if (!find (basepath, child, separator, out, cancellable, error))
- goto out;
- }
-
- child_path = ot_gfile_get_path_cached (child);
- child_trimmed_path = g_string_new (child_path + strlen (basepath));
- if (!*(child_trimmed_path->str))
- {
- /* do nothing - we implicitly add the root . */
- }
- else
- {
- g_assert (*(child_trimmed_path->str) == '/');
- g_string_insert_c (child_trimmed_path, 0, '.');
-
- if (!g_output_stream_write_all (out, child_trimmed_path->str, child_trimmed_path->len,
- &bytes_written, cancellable, error))
- goto out;
- buf[0] = separator;
- if (!g_output_stream_write_all (out, buf, 1, &bytes_written,
- cancellable, error))
- goto out;
- }
-
- ret = TRUE;
- out:
- g_string_free (child_trimmed_path, TRUE);
- child_trimmed_path = NULL;
- child_path = NULL;
- g_clear_object (&child);
- return ret;
-}
-
-static gboolean
-find (const char *basepath,
- GFile *dir,
- char separator,
- GOutputStream *out,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- GError *temp_error = NULL;
- GFileEnumerator *enumerator = NULL;
- GFileInfo *finfo = NULL;
-
- enumerator = g_file_enumerate_children (dir, "standard::type,standard::name",
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!enumerator)
- goto out;
-
- while ((finfo = g_file_enumerator_next_file (enumerator, cancellable, error)) != NULL)
- {
- if (!find_write_child (basepath, dir, separator, out, finfo, cancellable, error))
- goto out;
- g_clear_object (&finfo);
- }
- if (temp_error)
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
-
- ret = TRUE;
- out:
- g_clear_object (&finfo);
- g_clear_object (&enumerator);
- return ret;
-}
-
-static gpointer
-find_thread (gpointer data)
-{
- FindThreadData *tdata = data;
- GError *error = NULL;
- const char *path;
-
- path = ot_gfile_get_path_cached (tdata->dir);
- if (!find (path, tdata->dir, tdata->separator, tdata->out,
- tdata->cancellable, &error))
- {
- g_printerr ("%s", error->message);
- g_clear_error (&error);
- }
- g_clear_object (&(tdata->dir));
- g_clear_object (&(tdata->out));
- return NULL;
-}
-
gboolean
ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **error)
{
GOptionContext *context;
gboolean ret = FALSE;
OstreeRepo *repo = NULL;
- char *dir = NULL;
+ char *dirpath = NULL;
+ GFile *dir = NULL;
GChecksum *commit_checksum = NULL;
char separator;
GVariant *metadata = NULL;
GMappedFile *metadata_mappedf = NULL;
GFile *metadata_f = NULL;
- gboolean temp_fd = -1;
- int pipefd[2] = { -1, -1 };
- GOutputStream *out = NULL;
- FindThreadData fdata;
context = g_option_context_new ("[DIR] - Commit a new revision");
g_option_context_add_main_entries (context, options, NULL);
goto out;
if (argc > 1)
- dir = g_strdup (argv[1]);
+ dirpath = g_strdup (argv[1]);
else
- dir = g_get_current_dir ();
+ dirpath = g_get_current_dir ();
- if (g_str_has_suffix (dir, "/"))
- dir[strlen (dir) - 1] = '\0';
+ if (g_str_has_suffix (dirpath, "/"))
+ dirpath[strlen (dirpath) - 1] = '\0';
- separator = separator_null ? '\0' : '\n';
-
- if (!*dir)
+ if (!*dirpath)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid empty directory");
goto out;
}
+ dir = ot_gfile_new_for_path (dirpath);
+
if (metadata_text_path || metadata_bin_path)
{
metadata_mappedf = g_mapped_file_new (metadata_text_path ? metadata_text_path : metadata_bin_path, FALSE, error);
goto out;
}
- if (!(from_file || from_fd >= 0 || from_stdin))
- {
- /* We're using the current directory */
-
- }
-
- if (from_stdin)
- from_fd = 0;
- else if (from_file)
- {
- temp_fd = ot_util_open_file_read (from_file, error);
- if (temp_fd < 0)
- {
- g_prefix_error (error, "Failed to open '%s': ", from_file);
- goto out;
- }
- from_fd = temp_fd;
- }
- else
- {
- if (pipe (pipefd) < 0)
- {
- ot_util_set_error_from_errno (error, errno);
- goto out;
- }
-
- out = (GOutputStream*)g_unix_output_stream_new (pipefd[1], TRUE);
- from_fd = pipefd[0];
-
- fdata.dir = ot_gfile_new_for_path (dir);
- fdata.separator = separator;
- fdata.out = out;
- fdata.cancellable = NULL;
-
- if (g_thread_create_full (find_thread, &fdata, 0, FALSE, FALSE, G_THREAD_PRIORITY_NORMAL, error) == NULL)
- goto out;
-
- out = NULL;
- }
-
- if (!ostree_repo_commit_from_filelist_fd (repo, branch, parent, subject, body, metadata,
- dir, from_fd, separator,
- &commit_checksum, error))
+ if (!ostree_repo_commit (repo, branch, parent, subject, body, metadata,
+ dir, &commit_checksum, NULL, error))
goto out;
ret = TRUE;
g_print ("%s\n", g_checksum_get_string (commit_checksum));
out:
- g_clear_object (&out);
- if (temp_fd >= 0)
- (void)close (temp_fd);
- if (pipefd[0] > 0)
- (void) close (pipefd[0]);
- if (pipefd[1] > 0)
- (void) close (pipefd[1]);
- g_free (dir);
+ g_free (dirpath);
+ g_clear_object (&dir);
if (metadata_mappedf)
g_mapped_file_unref (metadata_mappedf);
if (context)